/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package control;

import java.util.LinkedList;
import java.util.Vector;
import model.Despachante;
import model.Processo;
import model.Processador;

/**
 *
 * @author
 * Abraão de Santana
 * Jorge Thiago
 * Leandro C. Arantes
 */
public class DespachanteFeedback implements Despachante {

    private LinkedList<Processo> mainQueue;
    private Vector<Processador> processors;

    private LinkedList<Processo> queue1 = new LinkedList<Processo>();
    private LinkedList<Processo> queue2 = new LinkedList<Processo>();
    private LinkedList<Processo> queue3 = new LinkedList<Processo>();

    private LinkedList<Processo> queue1ExecutingProcesses = new LinkedList<Processo>();
    private LinkedList<Processo> queue2ExecutingProcesses = new LinkedList<Processo>();
    private LinkedList<Processo> queue3ExecutingProcesses = new LinkedList<Processo>();

    public DespachanteFeedback() {
    }

    public DespachanteFeedback(LinkedList<Processo> FU, Vector<Processador> processors) {
        this.mainQueue = FU;
        this.processors = processors;
    }

    public void activate(Processador processor)
    {
        update(true);

        if ( !queue1.isEmpty() )
        {
            searchProcessToActivate(1, processor);
        }
        else if ( !queue2.isEmpty() )
        {
            searchProcessToActivate(2, processor);
        }
        else if ( !queue3.isEmpty() )
        {
            searchProcessToActivate(3, processor);
        }
    }

    private void searchProcessToActivate( int queueNumber, Processador processor )
    {
        LinkedList<Processo> queue = null;
        switch ( queueNumber )
        {
            case 1 :
            {
                queue = queue1;
                break;
            }
            case 2 :
            {
                queue = queue2;
                break;
            }
            case 3 :
            {
                queue = queue3;
                break;
            }
        }

        for ( int i = 0; i < queue.size(); i++ )
        {
            Processo process = queue.get(i);
            if ( processor.getMemoria().contemProcesso(process) )
            {
                processor.setProcessoAtivo(process);
                processor.setExecutando(true);
                queue.remove(i);
                switch ( queueNumber )
                {
                    case 1 :
                    {
                        queue1ExecutingProcesses.add(process);
                        break;
                    }
                    case 2 :
                    {
                        queue2ExecutingProcesses.add(process);
                        break;
                    }
                    case 3 :
                    {
                        queue3ExecutingProcesses.add(process);
                        break;
                    }
                }

                break;
            }
        }
    }

    public void update( boolean aProcessorIsEmpty )
    {
        for ( int i = 0; i < mainQueue.size(); )
        {
            Processo process = mainQueue.get(i);
            switch ( process.getPrioridade() )
            {
                case 1 :
                {
                    queue1.add(process);
                    if ( !aProcessorIsEmpty )
                    {
                        int random = (int) ( Math.random() * 3 );
                        Processador processor = processors.get(random);
                        if ( processor.isExecutando() && processor.getProcessoAtivo() != null && processor.getProcessoAtivo().getPrioridade() != 0 )
                        {
                            processor.paraProcessoAtual();
                        }
                        else
                        {
                            int count = 0;
                            boolean stoped = false;
                            while ( !stoped && count < 4 )
                            {
                                if ( random == 3 )
                                {
                                    random = 0;
                                }
                                else
                                {
                                    random++;
                                }

                                processor = processors.get(random);
                                if ( processor.isExecutando() && processor.getProcessoAtivo() != null && processor.getProcessoAtivo().getPrioridade() != 0 )
                                {
                                    processor.paraProcessoAtual();
                                    stoped = true;
                                }
                                else
                                {
                                    count++;
                                }
                            }
                        }
                    }
                    break;
                }
                case 2 :
                {
                    queue2.add(process);
                    break;
                }
                case 3 :
                {
                    queue3.add(process);
                    break;
                }
            }
            mainQueue.remove(process);
        }
    }

}
